import os
import json
from flask import Flask, request, jsonify, session
from docx import Document
from openai import OpenAI
from pymongo import MongoClient
import requests
from werkzeug.security import generate_password_hash, check_password_hash
import logging
import datetime
from difflib import SequenceMatcher
import re
import time
from ai_chatbot.tools import web_search as ws
from ai_chatbot.tools import file_parsing as fp
from ai_chatbot.tools import vector_db as vdb
from ai_chatbot.tools import os_api as oa
from ai_chatbot.tools import users_account as ua


# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

app = Flask(__name__)
app.secret_key = os.urandom(24)

# 使用 MongoDB 存储历史记录
client_his = MongoClient('mongodb://localhost:27017/')
db_his = client_his['chat_history']
history_collection = db_his['conversations']

# MongoDB 用户数据库配置
client_user = MongoClient('mongodb://localhost:27017/')
db_user = client_user['user_database']
user_collection = db_user['users']

#openai api配置
client_ai = OpenAI(
    api_key = "c27a61cf-658c-4b54-a4e9-d1a4574e6738",
    base_url = "https://ark.cn-beijing.volces.com/api/v3",
)

# 定义不确定回答的参考句子
UNCERTAIN_RESPONSES = [
    "答案未知", "答案不确定", "答案不明确", "没有科学依据", "没有确定的答案",
    "没有正确答案", "争论很多", "没有已知案例", "这个问题没有具体答案",
    "没有公开信息", "不可能知道", "无法回答", "难以预测", "不知道", "我们不知道", "我不确定","无法实时","无法直接","无法获取","无法查询"
]

# 计算文本相似度的函数
def calculate_similarity(text1, text2):
    return SequenceMatcher(None, text1, text2).ratio()

# 检测模型是否不知道答案
def detect_uncertainty(response):
    for uncertain_response in UNCERTAIN_RESPONSES:
        if calculate_similarity(response, uncertain_response) > 0.75:
            return True
    return False


# 查询 AI 函数
def query_ai(prompt, context=[]):
    """
    向DeepSeek AI接口发送查询请求
    参数:
        prompt (str): 用户输入的提问内容
        context (list): 上下文信息列表，默认为空列表
    返回:
        dict: 包含AI响应结果的JSON对象
    """
    # 确保 context 中的 role 值符合要求
    valid_context = []
    for msg in context:
        if msg['role'] == 'ai':
            valid_context.append({'role': 'assistant', 'content': msg['content']})
        else:
            valid_context.append(msg)

    # 合并上下文和当前提问
    messages = valid_context + [
        {
            "role": "system", 
            "content": "你是周吃饭，一位知识渊博的大学教授，你更擅长中文和英文的对话。你会为用户提供安全，有帮助，准确的回答。同时，你会拒绝一切涉及恐怖主义，种族歧视，黄色暴力等问题的回答。你很擅长推理，会参考历史对话分析用户的问题，但又不完全之参照历史对话。你的回答必须是 JSON 格式，包含三对键值：'knowornot'、'fuction' 和 'ai_return'。'knowornot' 的值只能是 '知道' 或 '不知道'。'fuction'的值有三个，当用户问到时间时，fuction的值为'time'，当用户问到天气时，fuction的值为'weather'，其余问题fuction的值为'search'。当 'knowornot' 为 '知道' 时，'ai_return' 的值为你的回答内容；当 'knowornot' 为 '不知道'且'fuction'值为'time' 时，'ai_return'的值按'(year=, month=, day=)'提取返回，如果不知道时间则返回'空'，当 'knowornot' 为 '不知道'且'fuction'值为'search' 时，'ai_return' 的值为将询问内容总结成的更适合查询的关键词。"
        },
        {
            "role": "user",
            "content": prompt
        }
    ]

    try:
        # 大模型调用
        response = client_ai.chat.completions.create(
            model='deepseek-r1-250528',
            messages=messages,
            temperature=0
        )
        model_response_text = response.choices[0].message.content
        logging.info("模型回答： %s", model_response_text)

        try:
            model_response = json.loads(model_response_text)
        except json.JSONDecodeError:
            logging.error("模型返回非 JSON 格式，尝试处理为知道答案")
            model_response = {
                "knowornot": "知道",
                "ai_return": model_response_text
            }

        # 根据 knowornot 的值确定是否调用搜索
        if model_response["knowornot"] == "知道":
            final_answer = model_response["ai_return"]
        else:
            if model_response["fuction"] == 'time':
                logging.info("模型不知道时间，需要调用系统时间。")
                # 联网搜索
                search_results = oa.get_system_time(model_response["ai_return"])
                
            elif  model_response["fuction"] == 'weather':
                logging.info("模型不知道天气，需要调用天气API。")
                # 联网搜索
                search_results = ws.web_search(model_response["ai_return"])
                
            else:       
                logging.info("模型不知道答案，需要联网搜索。")
                # 联网搜索
                search_results = ws.web_search(model_response["ai_return"])
                # logging.info("搜索结果： %s", search_results)
            # 结果整合
            integrate_response = client_ai.chat.completions.create(
                model='deepseek-r1-250528',
                messages=[
                    {"role": "user", "content": f"请根据以下搜索结果给出总结性报告：{search_results} 100字以内"}
                ],
                temperature=0
            )
            final_answer = integrate_response.choices[0].message.content

        return {
            "text": final_answer,
            "confidence": 1.0  # 实际应根据API响应添加置信度判断
        }
    except Exception as e:
        # 确保异常时返回字典类型
        return {
            "text": f"错误：{str(e)}",
            "confidence": 0.0
        }



# 注册接口
@app.route('/api/register', methods=['POST'])
def register():
    return ua.register()


# 登录接口
@app.route('/api/login', methods=['POST'])
def login():
    return ua.login()

    
# 检查登录状态接口
@app.route('/api/check_login', methods=['GET'])
def check_login():
    return ua.check_login()


# 注销接口
@app.route('/api/logout', methods=['POST'])
def logout():
    return ua.logout()


# 获取用户聊天历史记录接口
@app.route('/api/history', methods=['GET'])
def get_history():
    return ua.get_history()
    

# 保存或更新历史记录接口
@app.route('/api/history', methods=['PUT'])
def update_history():
    return ua.update_history()


# 删除历史记录接口
@app.route('/api/history/<conversation_id>', methods=['DELETE'])
def delete_history(conversation_id):
    return ua.delete_history(conversation_id)


# 保存新对话
@app.route('/api/history', methods=['POST'])
def save_conversation():
    return ua.save_conversation()


# 更新对话
@app.route('/api/history', methods=['PUT'])
def update_conversation():
    return ua.update_conversation()


# 删除对话
@app.route('/api/history/<int:conversation_id>', methods=['DELETE'])
def delete_conversation(conversation_id):
    return ua.delete_conversation(conversation_id)
 


@app.route('/api/chat', methods=['POST'])
def chat():
    if 'user_id' not in session:
        return jsonify({'message': '请先登录'}), 401
    print("[DEBUG] 收到请求，表单数据:", request.form)
    print("[DEBUG] 上传文件:", request.files)
    # 处理文件上传
    file = request.files.get('file')
    text = request.form.get('query')
    history_json = request.form.get('history')
    history = json.loads(history_json) if history_json else []

    if file:
        file_path = f"uploads/{file.filename}"
        file.save(file_path)
        text += fp.extract_text(file_path)

    # 截取最近的 3 轮历史对话
    recent_history = history[-6:] if len(history) > 6 else history
    # 调用AI模型，传递最近 3 轮历史对话
    ai_response = query_ai(text, recent_history)

    print("[DEBUG] 最终响应:", ai_response)
    return jsonify({"response": ai_response['text']})



# API 网关接口
@app.route('/api/gateway', methods=['POST'])
def api_gateway():
    data = request.get_json()
    question = data.get('question')
    if not question:
        return jsonify({'message': '问题不能为空'}), 400
    
    # 转发至时间处理服务
    return time_processing_service(question)



def time_processing_service(question):
    # 判断是否需要实时工具
    if "现在几点了？" in question:
        time_data = get_current_time()
        standardized_time = standardize_time_data(time_data)
        final_answer = integrate_time_to_answer(question, standardized_time)
        return jsonify({'answer': final_answer})
    else:
        # 若不是时间相关问题，可调用原有的 AI 回答逻辑
        ai_response = query_ai(question)
        return jsonify({'answer': ai_response['text']})

def get_current_time():
    try:
        # 先尝试调用第三方时间 API
        response = requests.get('https://worldtimeapi.org/api/ip')
        if response.status_code == 200:
            return response.json()
    except Exception as e:
        logging.error(f'调用第三方时间 API 失败: {str(e)}')
    
    # 若第三方 API 失败，获取服务器本地时间
    local_time = datetime.datetime.now()
    return {
        'datetime': local_time.strftime('%Y-%m-%dT%H:%M:%S.%f%z'),
        'timezone': str(local_time.tzinfo)
    }

def standardize_time_data(time_data):
    dt = datetime.datetime.fromisoformat(time_data['datetime'])
    return dt.strftime('%Y 年 %m 月 %d 日 %H 时 %M 分 %S 秒')

def integrate_time_to_answer(question, time_data):
    return f"{question} 现在是 {time_data}"



if __name__ == '__main__':
    if not os.path.exists('uploads'):
        os.makedirs('uploads')
    app.run(debug=True, threaded=False, processes=1)  # 禁用多线程和多进程